using System;
using CthulhuDomain.StageManagement;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

namespace CthulhuDomain.Services
{
  public class StateManager
  {
    private static volatile StateManager instance;
    private static readonly object syncRoot = new Object();
    public static long CurrentScore = 0;

    public static StateManager Instance
    {
      get
      {
        if (instance == null)
        {
          lock (syncRoot)
          {
            if (instance != null) return instance;
            instance = new StateManager();
          }
        }

        return instance;
      }
    }

    public static IGameServiceProvider GameServiceManager { get; set; }
    public static Stage CurrentStage { get; set; }
    protected static int Level { get; set; }

    public static void Initialize(IGameServiceProvider gameServiceManager)
    {
      GameServiceManager = gameServiceManager;
      CurrentStage = StageFactory.GetFactory(StageFactory.eTypeStage.Menu, GameServiceManager).CreateEntity();
      CurrentStage.Initialize();
    }

    public static void LoadContent()
    {
      CurrentStage.LoadContent();
    }

    public static void Update(Keys[] pressedKeys, IGameTime gameTime)
    {
      Level = CurrentStage.Level;
      var result = CurrentStage.Update(GameServiceManager.Context, pressedKeys, gameTime);
      switch (result.Result)
      {
        case eStateManagerResult.NewLevel:
          CurrentScore += result.Score;
          CurrentStage = new LevelStage(GameServiceManager,
                                        new StateManagerResult(result.Result, result.LifePoints, result.Score), ++ Level);

          break;
        case eStateManagerResult.GameOver:
          CurrentStage = new GameOverStage(GameServiceManager, result.Score);
          break;
      }
    }

    public static void Draw()
    {
      if (GameServiceManager.SpriteBatch.GraphicsDevice != null)
        if (CurrentStage != null)
          if (CurrentStage.BackgroundColor != null)
            GameServiceManager.SpriteBatch.GraphicsDevice.Clear(CurrentStage.BackgroundColor.Adaptee);
      if (GameServiceManager.SpriteBatch != null) GameServiceManager.SpriteBatch.Begin();

      if (CurrentStage != null) CurrentStage.Draw();

      if (GameServiceManager.SpriteBatch != null) GameServiceManager.SpriteBatch.End();
    }
  }

  [Flags]
  public enum eStateManagerResult
  {
    None = 0,
    Continue = 1 << 0,
    GameOver = 1 << 1,
    NewLevel = 1 << 2,
    PowerUp = 1 << 3
  }

  #region game time

  public class GameTimeAdapter : IGameTime
  {
    public GameTimeAdapter(GameTime gameTime)
    {
      Adaptee = gameTime;
    }

    private GameTime Adaptee { get; set; }

    #region IGameTime Members

    public TimeSpan ElapsedGameTime
    {
      get { return Adaptee.ElapsedGameTime; }
    }

    #endregion
  }

  public interface IGameTime
  {
    TimeSpan ElapsedGameTime { get; }
  }

  #endregion
}